package top.v5it.japi.ddd.tool;

import cn.hutool.core.util.StrUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhanpu
 * @date 2023/4/11
 */
public class TableToServiceImplTemplate {

    static String serviceImplPackageName = "top.v5it.japi.ddd.example.account.service.impl";
    static String pojoPackageName = "top.v5it.japi.ddd.example.account.entity";

    public static void main(String[] args) throws IOException {
        String url = "jdbc:mysql://10.173.234.101:3306/hoft-platform";
        String user = "root";
        String password = "3wax#EDC1014";
        String outputDir = "/home/bruce/test/service/impl";

        Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);
        cfg.setClassForTemplateLoading(TableToServiceImplTemplate.class, "/");
        Template template = cfg.getTemplate("ServiceImpl-template.java.ftl");

        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            List<Map<String, Object>> vos = getTables(conn, "hoft-platform", "root", "tb\\_%");
            for (Map<String, Object> dataModel : vos) {
                dataModel.put("serviceImplPackageName", serviceImplPackageName);
                dataModel.put("entityPackageName", pojoPackageName);
                File outputDirFile = new File(outputDir);
                final Object className = dataModel.get("className");
                FileWriter out = new FileWriter(new File(outputDirFile, className + ".java"));
                template.process(dataModel, out);

                out.flush();
                out.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取表信息
     *
     * @param conn
     * @param catalog
     * @param schemaPattern
     * @param tableNamePattern
     * @return
     */
    public static List<Map<String, Object>> getTables(Connection conn, String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
        final List<Map<String, Object>> vos = new ArrayList<>();

        try (final ResultSet tables = conn.getMetaData().getTables(catalog, schemaPattern, tableNamePattern, new String[]{"TABLE"})) {
            while (tables.next()) {
                final Map<String, Object> vo = new HashMap<>();
                final String tableName = tables.getString("TABLE_NAME");
                final String name = StrUtil.removePrefix(tableName, "tb_");
                final String className = toCamelCase(name, true);

                vo.put("className", String.format("%sServiceImpl", className));
                vo.put("entityName", className);
                vo.put("classServiceName", String.format("%sService", className));

                vos.add(vo);
            }
        }

        return vos;
    }

    /**
     * 格式转换，下划线转换驼峰式
     *
     * @param str
     * @param capitalizeFirstLetter 是否首字母大写
     * @return
     */
    private static String toCamelCase(String str, boolean capitalizeFirstLetter) {
        StringBuilder sb = new StringBuilder();
        boolean shouldCapitalize = capitalizeFirstLetter;
        for (char c : str.toCharArray()) {
            if (c == '_') {
                shouldCapitalize = true;
            } else {
                sb.append(shouldCapitalize ? Character.toUpperCase(c) : c);
                shouldCapitalize = false;
            }
        }
        return sb.toString();
    }
}
